package com.example.javaproject.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.javaproject.common.R;
import com.example.javaproject.entity.Student;
import com.example.javaproject.entity.User;
import com.example.javaproject.entity.PositionApplication;
import com.example.javaproject.entity.Position;
import com.example.javaproject.entity.WorkTimeRecord;
import com.example.javaproject.entity.Salary;
import com.example.javaproject.service.StudentService;
import com.example.javaproject.service.UserService;
import com.example.javaproject.service.PositionApplicationService;
import com.example.javaproject.service.PositionService;
import com.example.javaproject.service.WorkTimeRecordService;
import com.example.javaproject.service.SalaryService;
import com.example.javaproject.util.JwtUtil;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.beans.factory.annotation.Value;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.io.IOException;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.Set;
import java.util.HashSet;

@RestController
@RequestMapping("/api/student")
public class StudentController {
    @Autowired
    private StudentService studentService;
    @Autowired
    private UserService userService;
    @Autowired
    private PositionApplicationService positionApplicationService;
    @Autowired
    private PositionService positionService;
    @Autowired
    private WorkTimeRecordService workTimeRecordService;
    @Autowired
    private SalaryService salaryService;

    @Value("${worktime.upload-dir:uploads}")
    private String uploadDir;

    @GetMapping("/profile")
    public R getProfile(@RequestHeader("Authorization") String authHeader) {
        if (authHeader == null || !authHeader.startsWith("Bearer ")) {
            return R.error("未登录");
        }
        String token = authHeader.substring(7);
        Claims claims = JwtUtil.parseToken(token);
        Integer userId = claims.get("userId", Integer.class);
        if (userId == null) {
            return R.error("无效token");
        }
        Student student = studentService.getByUserId(userId);
        User user = userService.getById(userId);
        if (student == null || user == null) {
            return R.error("未找到学生或用户信息");
        }
        return R.ok(new StudentProfileVO(
            user.getUsername(), user.getPassword(), user.getMail(), user.getPhone(),
            student.getName(), student.getCollege(), student.getContact(), student.getCreateTime(), student.getUpdateTime()
        ));
    }

    @PutMapping("/profile")
    public R updateProfile(@RequestHeader("Authorization") String authHeader, @RequestBody StudentProfileUpdateDTO updateDTO) {
        if (authHeader == null || !authHeader.startsWith("Bearer ")) {
            return R.error("未登录");
        }
        String token = authHeader.substring(7);
        Claims claims = JwtUtil.parseToken(token);
        Integer userId = claims.get("userId", Integer.class);
        if (userId == null) {
            return R.error("无效token");
        }
        
        try {
            // 更新用户信息
            User user = userService.getById(userId);
            if (user == null) {
                return R.error("用户不存在");
            }
            user.setUsername(updateDTO.username);
            user.setPassword(updateDTO.password);
            user.setMail(updateDTO.mail);
            user.setPhone(updateDTO.phone);
            user.setUpdateTime(java.time.LocalDateTime.now());
            userService.updateById(user);
            
            // 更新学生信息
            Student student = studentService.getByUserId(userId);
            if (student == null) {
                return R.error("学生信息不存在");
            }
            student.setName(updateDTO.name);
            student.setCollege(updateDTO.college);
            student.setContact(updateDTO.contact);
            student.setUpdateTime(LocalDateTime.now());
            studentService.updateById(student);
            
            return R.ok("更新成功");
        } catch (Exception e) {
            return R.error("更新失败: " + e.getMessage());
        }
    }

    @GetMapping("/my-position")
    public R getMyPositions(@RequestHeader("Authorization") String authHeader,
                           @RequestParam(defaultValue = "1") int pageNum,
                           @RequestParam(defaultValue = "8") int pageSize) {
        if (authHeader == null || !authHeader.startsWith("Bearer ")) {
            return R.error("未登录");
        }
        String token = authHeader.substring(7);
        Claims claims = JwtUtil.parseToken(token);
        Integer userId = claims.get("userId", Integer.class);
        if (userId == null) {
            return R.error("无效token");
        }
        // 1. 通过userId查studentId
        Student student = studentService.getByUserId(userId);
        if (student == null) {
            return R.error("未找到学生信息");
        }
        Integer studentId = student.getId();
        // 2. 查岗位申请表，status=1，is_deleted=0，student_id=studentId
        Page<PositionApplication> page = new Page<>(pageNum, pageSize);
        IPage<PositionApplication> appPage = positionApplicationService.lambdaQuery()
                .eq(PositionApplication::getStatus, 1)
                .eq(PositionApplication::getIsDeleted, 0)
                .eq(PositionApplication::getStudentId, studentId)
                .orderByDesc(PositionApplication::getUpdateTime)
                .page(page);
        List<Map<String, Object>> result = new ArrayList<>();
        Set<Integer> addedPositionIds = new HashSet<>();
        List<Map<String, Object>> allPositions = new ArrayList<>();
        for (PositionApplication app : appPage.getRecords()) {
            Position pos = positionService.getActiveById(app.getPositionId());
            if (pos == null) continue;
            if (addedPositionIds.contains(pos.getId())) continue;
            addedPositionIds.add(pos.getId());
            List<WorkTimeRecord> records = workTimeRecordService.lambdaQuery()
                    .eq(WorkTimeRecord::getStudentId, studentId)
                    .eq(WorkTimeRecord::getPositionId, app.getPositionId())
                    .eq(WorkTimeRecord::getIsDeleted, 0)
                    .list();
            double totalHours = 0;
            for (WorkTimeRecord rec : records) {
                if (rec.getStartTime() != null && rec.getEndTime() != null) {
                    try {
                        java.time.LocalTime start = rec.getStartTime().toLocalTime();
                        java.time.LocalTime end = rec.getEndTime().toLocalTime();
                        java.time.Duration duration = java.time.Duration.between(start, end);
                        totalHours += duration.toMinutes() / 60.0;
                    } catch (Exception ignore) {}
                }
            }
            Map<String, Object> map = new HashMap<>();
            map.put("positionName", pos.getName());
            map.put("description", pos.getDescription());
            map.put("location", pos.getLocation());
            map.put("salary", pos.getSalary());
            map.put("workTime", pos.getTime());
            map.put("totalHours", String.format("%.1f", totalHours));
            map.put("id", pos.getId()); // 补充id，前端分页需要
            allPositions.add(map);
        }
        // 重新分页
        int totalPositions = allPositions.size();
        int fromIndex = Math.min((pageNum - 1) * pageSize, totalPositions);
        int toIndex = Math.min(pageNum * pageSize, totalPositions);
        result = allPositions.subList(fromIndex, toIndex);
        Map<String, Object> pageData = new HashMap<>();
        pageData.put("records", result);
        pageData.put("total", totalPositions);
        return R.ok(pageData);
    }

    @GetMapping("/work-time-positions")
    public R getWorkTimePositions(@RequestHeader("Authorization") String authHeader) {
        if (authHeader == null || !authHeader.startsWith("Bearer ")) {
            return R.error("未登录");
        }
        String token = authHeader.substring(7);
        Claims claims = JwtUtil.parseToken(token);
        Integer userId = claims.get("userId", Integer.class);
        if (userId == null) {
            return R.error("无效token");
        }
        // 1. 通过userId查studentId
        Student student = studentService.getByUserId(userId);
        if (student == null) {
            return R.error("未找到学生信息");
        }
        Integer studentId = student.getId();
        // 2. 查岗位申请表，status=1，is_deleted=0，student_id=studentId
        List<PositionApplication> appList = positionApplicationService.lambdaQuery()
                .eq(PositionApplication::getStatus, 1)
                .eq(PositionApplication::getIsDeleted, 0)
                .eq(PositionApplication::getStudentId, studentId)
                .list();
        // 只保留唯一的岗位id
        Set<Integer> positionIds = new HashSet<>();
        for (PositionApplication app : appList) {
            positionIds.add(app.getPositionId());
        }
        List<Map<String, Object>> result = new ArrayList<>();
        for (Integer posId : positionIds) {
            Position pos = positionService.getById(posId);
            if (pos != null) {
                Map<String, Object> map = new HashMap<>();
                map.put("id", pos.getId());
                map.put("name", pos.getName());
                result.add(map);
            }
        }
        return R.ok(result);
    }

    @PostMapping("/work-time-record")
    public R submitWorkTimeRecord(
            @RequestHeader("Authorization") String authHeader,
            @RequestParam String positionName,
            @RequestParam String positionDescription,
            @RequestParam String positionLocation,
            @RequestParam String positionWorkTime,
            @RequestParam Integer positionSalary,
            @RequestParam String startTime,
            @RequestParam String endTime,
            @RequestParam String description,
            @RequestParam("file") MultipartFile file
    ) {
        if (authHeader == null || !authHeader.startsWith("Bearer ")) {
            return R.error("未登录");
        }
        String token = authHeader.substring(7);
        Claims claims = JwtUtil.parseToken(token);
        Integer userId = claims.get("userId", Integer.class);
        if (userId == null) {
            return R.error("无效token");
        }
        // 1. 查studentId
        Student student = studentService.getByUserId(userId);
        if (student == null) {
            return R.error("未找到学生信息");
        }
        Integer studentId = student.getId();
        
        // 2. 联合查找岗位
        Position pos = positionService.lambdaQuery()
            .eq(Position::getName, positionName)
            .eq(Position::getDescription, positionDescription)
            .eq(Position::getLocation, positionLocation)
            .eq(Position::getTime, positionWorkTime)
            .eq(Position::getSalary, positionSalary)
            .one();
        if (pos == null) {
            return R.error("岗位不存在");
        }
        Integer positionId = pos.getId();
        Integer teacherId = pos.getTeacherId();
        
        // 3. 验证学生是否有权限申请该岗位（检查岗位申请表）
        boolean hasPermission = positionApplicationService.lambdaQuery()
                .eq(PositionApplication::getStudentId, studentId)
                .eq(PositionApplication::getPositionId, positionId)
                .eq(PositionApplication::getStatus, 1) // 已通过
                .eq(PositionApplication::getIsDeleted, 0)
                .exists();
        if (!hasPermission) {
            return R.error("您没有权限申请该岗位");
        }
        
        // 4. 保存图片
        String fileUrl = null;
        if (file != null && !file.isEmpty()) {
            try {
                // 获取项目根目录
                String rootPath = System.getProperty("user.dir");
                Path uploadPath = Paths.get(rootPath, uploadDir);
                if (!Files.exists(uploadPath)) {
                    Files.createDirectories(uploadPath);
                }
                String filename = System.currentTimeMillis() + "_" + file.getOriginalFilename();
                Path filePath = uploadPath.resolve(filename);
                file.transferTo(filePath.toFile());
                fileUrl = "/uploads/" + filename; // 前端访问路径
            } catch (IOException e) {
                return R.error("图片上传失败: " + e.getMessage());
            }
        }
        
        // 5. 解析日期时间
        try {
            // 解析开始时间 "2023-03-01 14:30:00" -> 日期: 2023-03-01, 时间: 14:30:00
            String[] startParts = startTime.split(" ");
            if (startParts.length != 2) {
                return R.error("开始时间格式错误");
            }
            String startDate = startParts[0];
            String startTimeOnly = startParts[1];
            
            // 解析结束时间
            String[] endParts = endTime.split(" ");
            if (endParts.length != 2) {
                return R.error("结束时间格式错误");
            }
            String endDate = endParts[0];
            String endTimeOnly = endParts[1];
            
            // 验证日期是否一致
            if (!startDate.equals(endDate)) {
                return R.error("开始日期和结束日期必须相同");
            }
            
            // 6. 插入work_time_record表
            WorkTimeRecord record = new WorkTimeRecord();
            record.setPositionId(positionId);
            record.setStudentId(studentId);
            record.setTeacherId(teacherId);
            record.setDate(java.sql.Date.valueOf(startDate)); // 设置日期
            record.setStartTime(java.sql.Time.valueOf(startTimeOnly)); // 设置开始时间
            record.setEndTime(java.sql.Time.valueOf(endTimeOnly)); // 设置结束时间
            record.setDescription(description);
            record.setProofUrl(fileUrl);
            record.setStatus(0); // 0:未审核
            record.setIsDeleted(false);
            record.setCreateTime(java.time.LocalDateTime.now());
            record.setUpdateTime(java.time.LocalDateTime.now());
            
            boolean success = workTimeRecordService.save(record);
            if (success) {
                return R.ok("提交成功");
            } else {
                return R.error("保存失败");
            }
        } catch (Exception e) {
            return R.error("时间格式处理失败: " + e.getMessage());
        }
    }

    @GetMapping("/work-time-records")
    public R getWorkTimeRecords(
            @RequestHeader("Authorization") String authHeader,
            @RequestParam(defaultValue = "1") int pageNum,
            @RequestParam(defaultValue = "8") int pageSize) {
        if (authHeader == null || !authHeader.startsWith("Bearer ")) {
            return R.error("未登录");
        }
        String token = authHeader.substring(7);
        Claims claims = JwtUtil.parseToken(token);
        Integer userId = claims.get("userId", Integer.class);
        if (userId == null) {
            return R.error("无效token");
        }
        // 1. 查studentId
        Student student = studentService.getByUserId(userId);
        if (student == null) {
            return R.error("未找到学生信息");
        }
        Integer studentId = student.getId();
        // 2. 查岗位申请表，获取所有通过的岗位id
        List<PositionApplication> appList = positionApplicationService.lambdaQuery()
                .eq(PositionApplication::getStatus, 1)
                .eq(PositionApplication::getIsDeleted, 0)
                .eq(PositionApplication::getStudentId, studentId)
                .list();
        Set<Integer> positionIds = new HashSet<>();
        for (PositionApplication app : appList) {
            positionIds.add(app.getPositionId());
        }
        // 3. 分页查work_time_record表
        Page<WorkTimeRecord> page = new Page<>(pageNum, pageSize);
        IPage<WorkTimeRecord> recordPage = workTimeRecordService.lambdaQuery()
                .eq(WorkTimeRecord::getStudentId, studentId)
                .in(positionIds.size() > 0, WorkTimeRecord::getPositionId, positionIds)
                .eq(WorkTimeRecord::getIsDeleted, 0)
                .orderByDesc(WorkTimeRecord::getCreateTime)
                .page(page);
        List<Map<String, Object>> result = new ArrayList<>();
        for (WorkTimeRecord rec : recordPage.getRecords()) {
            Map<String, Object> map = new HashMap<>();
            Position pos = positionService.getById(rec.getPositionId());
            map.put("positionName", pos != null ? pos.getName() : "-");
            map.put("date", rec.getDate());
            map.put("startTime", rec.getStartTime());
            map.put("endTime", rec.getEndTime());
            map.put("description", rec.getDescription());
            map.put("status", rec.getStatus());
            result.add(map);
        }
        Map<String, Object> pageData = new HashMap<>();
        pageData.put("records", result);
        pageData.put("total", recordPage.getTotal());
        return R.ok(pageData);
    }

    @GetMapping("/dashboard-stats")
    public R getDashboardStats(@RequestHeader("Authorization") String authHeader) {
        if (authHeader == null || !authHeader.startsWith("Bearer ")) {
            return R.error("未登录");
        }
        String token = authHeader.substring(7);
        Claims claims = JwtUtil.parseToken(token);
        Integer userId = claims.get("userId", Integer.class);
        if (userId == null) {
            return R.error("无效token");
        }
        
        // 1. 通过userId查studentId
        Student student = studentService.getByUserId(userId);
        if (student == null) {
            return R.error("未找到学生信息");
        }
        Integer studentId = student.getId();
        
        // 2. 获取我的申请数量（所有状态的申请）
        long applicationsCount = positionApplicationService.lambdaQuery()
                .eq(PositionApplication::getStudentId, studentId)
                .eq(PositionApplication::getIsDeleted, 0)
                .count();
        
        // 3. 获取本月工时（以创建时间为准）
        java.time.LocalDateTime now = java.time.LocalDateTime.now();
        java.time.LocalDateTime startOfMonth = now.withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0).withNano(0);
        java.time.LocalDateTime endOfMonth = now.withDayOfMonth(now.toLocalDate().lengthOfMonth()).withHour(23).withMinute(59).withSecond(59).withNano(999999999);

        List<WorkTimeRecord> monthRecords = workTimeRecordService.lambdaQuery()
                .eq(WorkTimeRecord::getStudentId, studentId)
                .eq(WorkTimeRecord::getIsDeleted, 0)
                .eq(WorkTimeRecord::getStatus, 1)
                .ge(WorkTimeRecord::getCreateTime, startOfMonth)
                .le(WorkTimeRecord::getCreateTime, endOfMonth)
                .list();

        double totalWorkHours = 0.0;
        for (WorkTimeRecord record : monthRecords) {
            if (record.getStartTime() != null && record.getEndTime() != null) {
                try {
                    java.time.LocalTime start = record.getStartTime().toLocalTime();
                    java.time.LocalTime end = record.getEndTime().toLocalTime();
                    java.time.Duration duration = java.time.Duration.between(start, end);
                    totalWorkHours += duration.toMinutes() / 60.0;
                } catch (Exception ignore) {}
            }
        }

        // 4. 获取本月工资（以创建时间为准）
        List<Salary> monthSalaries = salaryService.lambdaQuery()
                .eq(Salary::getStudentId, studentId)
                .eq(Salary::getStatus, 1)
                .eq(Salary::getIsDeleted, 0)
                .ge(Salary::getCreateTime, startOfMonth)
                .le(Salary::getCreateTime, endOfMonth)
                .list();

        double totalSalary = 0.0;
        for (Salary salary : monthSalaries) {
            if (salary.getTotalSalary() != null) {
                totalSalary += salary.getTotalSalary().doubleValue();
            }
        }

        Map<String, Object> stats = new HashMap<>();
        stats.put("applications", applicationsCount);
        stats.put("workHours", Math.round(totalWorkHours * 10.0) / 10.0); // 保留一位小数
        stats.put("salary", Math.round(totalSalary * 100.0) / 100.0); // 保留两位小数
        
        return R.ok(stats);
    }

    static class StudentProfileVO {
        public String username;
        public String password;
        public String mail;
        public String phone;
        public String name;
        public String college;
        public String contact;
        public Object createTime;
        public Object updateTime;
        public StudentProfileVO(String username, String password, String mail, String phone, String name, String college, String contact, Object createTime, Object updateTime) {
            this.username = username;
            this.password = password;
            this.mail = mail;
            this.phone = phone;
            this.name = name;
            this.college = college;
            this.contact = contact;
            this.createTime = createTime;
            this.updateTime = updateTime;
        }
    }

    static class StudentProfileUpdateDTO {
        public String username;
        public String password;
        public String mail;
        public String phone;
        public String name;
        public String college;
        public String contact;
    }
}
